package com.leyou.gateway.filters;

import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.utils.CookieUtils;
import com.leyou.gateway.config.FilterProperties;
import com.leyou.gateway.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 过滤器，权限校验
 */
@Slf4j
@Component
@EnableConfigurationProperties({JwtProperties.class, FilterProperties.class})
public class AuthFilter extends ZuulFilter {

    @Autowired
    private JwtProperties jwtProp;

    @Autowired
    private FilterProperties filterProp;


    /**
     * pre类型的过滤器会让请求在路由之前被执行
     * @return
     */
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    /**
     * 执行的优先级顺序，该数值越小，优先级越高
     * @return
     */
    @Override
    public int filterOrder() {
        return FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER - 1;
    }

    /**
     * 是否执行此过滤器
     * 此方法返回false时，会将请求放行，也就是不走run()方法了
     * @return
     */
    @Override
    public boolean shouldFilter() {
        //获取上下文对象
        RequestContext context = RequestContext.getCurrentContext();

        //获取请求对象
        HttpServletRequest request = context.getRequest();

        String uri = request.getRequestURI();

        return !isAllowPath(uri);
    }

    private boolean isAllowPath(String url){
        List<String> paths = filterProp.getAllowPaths();
        //如果是需要被放行的路径，返回true,取反后，变为 false
        for (String path : paths) {
            if (url.startsWith(path)){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取用户角色，获取角色与权限
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        //获取上下文对象
        RequestContext context = RequestContext.getCurrentContext();

        //获取请求对象
        HttpServletRequest request = context.getRequest();

        try {
            //获取token
            String token = CookieUtils.getCookieValue(request, jwtProp.getUser().getCookieName());

            //获取用户信息
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, jwtProp.getPublicKey(), UserInfo.class);

            UserInfo user = payload.getInfo();

            //查询角色 ，获取权限
            String role = user.getRole();

            //获取请求路径
            String path = request.getRequestURI();

            //获取请求方法
            String method = request.getMethod();

            // TODO 判断权限，此处暂时空置，等待权限服务完成后补充
            log.info("【网关】用户{},角色{}。访问服务{} : {}，", user.getUsername(), role, method, path);
        } catch (Exception e) {
            context.setSendZuulResponse(false);
            context.setResponseStatusCode(403);
            log.error("非法访问，未登录，地址：{}", request.getRemoteHost(), e );
        }

        return null;
    }
}
